home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / sviluppo / svilupp2 / amphn192.lha / src / phoneudp.c < prev    next >
C/C++ Source or Header  |  1996-11-16  |  10KB  |  371 lines

  1. #define DICE_C
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. #include <string.h>
  7. #include <time.h>
  8.  
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <libraries/dos.h>            /* contains RETURN_OK, RETURN_WARN #def's */
  12. #include <dos/dosextens.h>
  13. #include <dos/var.h>
  14. #include <clib/exec_protos.h>
  15. #include <clib/intuition_protos.h>
  16. #include <clib/dos_protos.h>
  17.  
  18. #include <intuition/intuition.h>
  19.  
  20. #include <graphics/gfxbase.h>
  21. #include <proto/socket.h>
  22. #include <sys/errno.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/syslog.h>
  27. #include <netdb.h>
  28. #include <amitcp/socketbasetags.h>
  29.  
  30. #include <pragmas/socket_pragmas.h>
  31. #include <inetd.h>
  32.  
  33. #include "AmiPhone.h"
  34. #include "AmiPhoneMsg.h"
  35. #include "StringRequest.h"
  36. #include "codec.h"
  37. #include "phoneudp.h"
  38. #include "TCPQueue.h"
  39.  
  40. /* Why does this come out as 18 unless I define it explicitely here?  Weird! */
  41. #define EWOULDBLOCK 35
  42.  
  43. /* Prototypes for the compression/decompression asm functions! */
  44. /* extern __asm ULONG CompressADPCM2(
  45.     register __a0 UBYTE *Source, register __d0 ULONG Length,
  46.     register __a1 UBYTE *Destination, register __d1 ULONG JoinCode);
  47.  
  48. extern __asm ULONG CompressADPCM3(
  49.     register __a0 UBYTE *Source, register __d0 ULONG Length,
  50.     register __a1 UBYTE *Destination,register __d1 ULONG JoinCode);
  51. */
  52.  
  53. extern FILE * fpMemo;
  54.  
  55. static struct sockaddr_in saTCPPeerAddress;
  56. static struct sockaddr_in saUDPPeerAddress;
  57. static struct hostent *hp;
  58. static struct servent *sp;
  59. static LONG lDataSeqNum = 1;
  60.  
  61. extern BOOL BNetConnect;
  62. extern BOOL BTransmitting;
  63. extern BOOL BTCPBatchXmit;
  64. extern ULONG ulKeyCode;
  65. extern ULONG ulBytesSentSince;
  66. extern struct AmiPhoneGraphicsInfo GraphInfo;
  67. extern struct MsgPort *PhonePort;
  68. extern struct Window * PhoneWindow;
  69. extern struct Screen * Scr;
  70.  
  71.  
  72. LONG   sTCPSocket=-1;
  73. static LONG   sUDPSocket=-1;
  74. static USHORT port;
  75.  
  76. int ClosePhoneSocket(void)
  77. {
  78.     struct sockaddr_in saBadAddress;
  79.     
  80.     saBadAddress.sin_family = AF_UNSPEC;
  81.     
  82.     FlushTCPQueue(0);
  83.     
  84.         UNLESS(SocketBase)return(FALSE);
  85.  
  86.     /* If we're not recording a memo, there's no reason to use the mic */
  87.     if (fpMemo == NULL) ToggleMicButton(CODE_OFF);
  88.  
  89.     if (sUDPSocket != -1)
  90.     {
  91.         connect(sUDPSocket,&saBadAddress, sizeof(saBadAddress));
  92.         CloseSocket(sUDPSocket); 
  93.         sUDPSocket = -1;
  94.     }
  95.  
  96.     if (sTCPSocket != -1) 
  97.     {
  98.         if (BNetConnect == TRUE) SendCommandPacket(PHONECOMMAND_DISCONNECT, 0, 0L);    
  99.         CloseSocket(sTCPSocket); 
  100.         sTCPSocket = -1;
  101.     }
  102.  
  103.     /* Tell our peer we're outta here */
  104.     BNetConnect = FALSE;        
  105.     
  106.     SetWindowTitle("Connection closed.");            
  107.     SetMenuValues();
  108.     return(TRUE);
  109. }
  110.  
  111.  
  112. void ChangeConnectPort(int nPortNum)
  113. {
  114.     int nSuccess;
  115.     
  116.     saUDPPeerAddress.sin_port = htons(nPortNum);
  117.     nSuccess = connect(sUDPSocket, (struct sockaddr *) &saUDPPeerAddress, sizeof(saUDPPeerAddress));
  118.     if (nSuccess < 0) printf("ChangeConnectPort: warning, connect failed: errno=%i\n",errno);
  119. }
  120.  
  121. BOOL SetAsyncMode(BOOL BAsynch, LONG sSocket)
  122. {
  123.     LONG lNonBlockCode = BAsynch;
  124.     
  125.     if (IoctlSocket(sSocket, FIONBIO, (char *)&lNonBlockCode) < 0) return(FALSE);
  126.     return(TRUE);
  127. }
  128.  
  129.  
  130.  
  131. /* Now connects initially with a TCP socket.  This allows us to
  132.    easily and reliably send commands. When we get a reply, we'll 
  133.    create a udp socket to send the actual data with. */
  134. int ConnectPhoneSocket(BOOL BShowRequester, char * szPeerName)
  135. {
  136.     int nSuccess;
  137.     char sBuffer[MAXPEERNAMELENGTH+30], *sTemp = sBuffer;   
  138.     char szTemp[20];
  139.     ULONG sec, mic;
  140.     BOOL BGenerateKey = (ulKeyCode == 0L);
  141.     static char szPortName[100];
  142.     const char szConnectionType[] = "tcp";
  143.     
  144.     UNLESS(SocketBase) return(FALSE);
  145.     
  146.     Strncpy(sBuffer,szPeerName,MAXPEERNAMELENGTH);    
  147.     
  148.     if ((BShowRequester == TRUE) && (GetUserString(Scr, PhoneWindow, sBuffer,"AmiPhone Connect","Enter Name of Remote Amiga",MAXPEERNAMELENGTH) == FALSE))
  149.     {
  150.         SetWindowTitle("Connect cancelled.");    
  151.         return(FALSE);
  152.     }
  153.     
  154.     /* If the user tries to put in a user account name, ignore it. */
  155.     if (strchr(sBuffer,'@') != NULL) sTemp = strchr(sBuffer,'@')+1;
  156.  
  157.     Strncpy(szPeerName, sTemp, MAXPEERNAMELENGTH);
  158.     LowerCase(szPeerName);
  159.  
  160.     if (strlen(szPeerName) == 0)
  161.     {
  162.         SetWindowTitle("Connect cancelled.");
  163.         return(FALSE);
  164.     }
  165.  
  166.     if (strcmp(szPeerName,"localhost") == 0)
  167.     {
  168.         if (gethostname(szPeerName,MAXPEERNAMELENGTH) < 0) 
  169.         {
  170.             SetWindowTitle("localhost's name is unavailable.");
  171.             return(FALSE);
  172.         }
  173.     }
  174.         
  175.     sprintf(sBuffer,"Looking up %s",szPeerName);
  176.     SetWindowTitle(sBuffer);
  177.     
  178.         SetErrnoPtr(&errno, sizeof(errno));
  179.     
  180.             sp = getservbyname("AmiPhone",szConnectionType);
  181.     if (sp == NULL) sp = getservbyname("Amiphone",szConnectionType);    /* Try almost all lowercase then! */    
  182.     if (sp == NULL) sp = getservbyname("amiPhone",szConnectionType);    /* Try almost all lowercase then! */    
  183.     if (sp == NULL) sp = getservbyname("amiphone",szConnectionType);    /* Try all lowercase then! */    
  184.     if (sp == NULL)
  185.     {
  186.         MakeReq(NULL,"Couldn't find tcp service entry for AmiPhone!","Better go check amitcp:db/services");
  187.         SetWindowTitle("Connect Failed.");
  188.         return(FALSE);
  189.     }
  190.     port = sp->s_port;
  191.  
  192.     hp = gethostbyname(szPeerName);
  193.     if (hp == NULL)
  194.     {
  195.         SetWindowTitle("Name lookup failed.");
  196.         return(FALSE);
  197.     }
  198.  
  199.     bzero(&saTCPPeerAddress, sizeof(saTCPPeerAddress));
  200.     bzero(&saUDPPeerAddress, sizeof(saUDPPeerAddress));
  201.     
  202.         bcopy(hp->h_addr, (char *)&saTCPPeerAddress.sin_addr, hp->h_length);
  203.         bcopy(hp->h_addr, (char *)&saUDPPeerAddress.sin_addr, hp->h_length);
  204.         
  205.     saTCPPeerAddress.sin_family = hp->h_addrtype;
  206.     saUDPPeerAddress.sin_family = hp->h_addrtype;
  207.     
  208.     saTCPPeerAddress.sin_port   = htons(port);    
  209.     /* UDP port will be set later, in ChangeConnectPort() */
  210.     
  211.     if ((sUDPSocket = socket(hp->h_addrtype,SOCK_DGRAM,0)) < 0)
  212.     {
  213.         SetWindowTitle("Connect Failed. (Couldn't get UDP socket)");
  214.         return(FALSE);
  215.     }
  216.     if ((sTCPSocket = socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)
  217.     {
  218.         SetWindowTitle("Connect Failed. (Couldn't get TCP socket)");
  219.         return(FALSE);
  220.     }
  221.         
  222.     sprintf(sBuffer,"Connecting to %s",szPeerName);
  223.     SetWindowTitle(sBuffer);
  224.     nSuccess = connect(sTCPSocket, (struct sockaddr *) &saTCPPeerAddress, sizeof(saTCPPeerAddress));
  225.     if (nSuccess < 0)
  226.     {
  227.         SetWindowTitle("Connect Failed.");
  228.         return(FALSE);
  229.     }
  230.  
  231.     SetAsyncMode(TRUE, sTCPSocket);
  232.  
  233.     /* If we already have a key, send it, else generate one at random */
  234.     if (BGenerateKey == TRUE)
  235.     {
  236.         /* seed the randomizer */
  237.         CurrentTime(&sec, &mic);
  238.         srand(mic);
  239.  
  240.         /* get a random keyvalue */
  241.         ulKeyCode = rand();
  242.         
  243.         /* Don't let it be zero though */
  244.         if (ulKeyCode == 0L) ulKeyCode++;
  245.     }
  246.  
  247.     BNetConnect = TRUE;    /* must be before SendCommandPacket(), so send isn't suppressed! */
  248.     if (SendCommandPacket(PHONECOMMAND_CONNECT, 0, ulKeyCode) == FALSE)
  249.     {
  250.         BNetConnect = FALSE;
  251.         SetWindowTitle("Couldn't send connect info");
  252.         return(FALSE);
  253.     }
  254.     
  255.     /* and since we might have a return call, use a port name AmiPhoned can find */
  256.     sprintf(szTemp,"%d",ulKeyCode);
  257.  
  258.     /* Open a local messaage port as something AmiPhoned can find */
  259.     sprintf(szPortName,"AmiPhone_%ld",ulKeyCode);
  260.         
  261.     /* Setup message port for talking to AmiPhoned */
  262.     PhonePort->mp_Node.ln_Name = szPortName;
  263.     PhonePort->mp_Node.ln_Pri  = 3;
  264.     AddPhonePort(TRUE);
  265.     
  266.     return(TRUE);
  267. }
  268.  
  269.  
  270.  
  271. /* This function sends the given packet header over the TCP link.  */
  272. BOOL SendCommandPacket(UBYTE ubCommand, UBYTE ubType, ULONG ulData)
  273. {
  274.     struct AmiPhonePacketHeader AmiPack;
  275.     
  276.     /* Don't send anything if there's no AmiTCP! */
  277.     UNLESS(SocketBase&&BNetConnect) return(FALSE);
  278.     
  279.     AmiPack.ubCommand = ubCommand;
  280.     AmiPack.ubType      = ubType;
  281.     AmiPack.ulBPS      = ulData;
  282.     AmiPack.lSeqNum   = -1;
  283.     AmiPack.ulDataLen = 0L;
  284.  
  285.     /* if we're beginning a new session, reset packet sequence number */
  286.     if (ubCommand == PHONECOMMAND_CONNECT) {lDataSeqNum = 1L; AmiPack.ulJoinCode = VERSION_NUMBER;}
  287.  
  288.     ulBytesSentSince += AttemptTCPSend(sTCPSocket, 0, (UBYTE *) &AmiPack, sizeof(struct AmiPhonePacketHeader));
  289.     return(TRUE);
  290. }
  291.  
  292.  
  293.  
  294.  
  295. /* Send a packet consisting of the given header, plus ulLen bytes
  296.    that are located after it. */
  297. /* Sending it a null pPack will only increase the Data sequencing number */
  298. BOOL SendPacket(struct AmiPhoneSendBuffer * pPack, BOOL BUseTCP)
  299. {
  300.     ULONG lSendLen;
  301.     int nBytesSent;
  302.     
  303.     if (pPack == NULL) 
  304.     {
  305.         lDataSeqNum++;
  306.         return;
  307.     }
  308.  
  309.     lSendLen = pPack->header.ulDataLen + sizeof(struct AmiPhonePacketHeader);
  310.     
  311.     if ((fpMemo == NULL)&&((BNetConnect == FALSE)||(SocketBase == NULL))) return(FALSE);
  312.     
  313.     /* keep a counter to ensure orderly playing of data */
  314.     pPack->header.lSeqNum = lDataSeqNum++;
  315.  
  316.     if ((SocketBase)&&(BNetConnect))
  317.     {
  318.         if (BUseTCP) nBytesSent = AttemptTCPSend(sTCPSocket, 0, (UBYTE *)pPack, lSendLen);
  319.             else nBytesSent = send(sUDPSocket, (UBYTE *)pPack, lSendLen, 0L);
  320.         SetWindowTitle(NULL);
  321.     }
  322.     else nBytesSent = lSendLen;    /* Only going to disk--fake okay send */
  323.  
  324.     ulBytesSentSince += ((nBytesSent > 0) ? nBytesSent : 0);
  325.  
  326.     /* If we're recording a memo, save the data to disk too */
  327.     if ((pPack->header.ubCommand == PHONECOMMAND_DATA)&&(fpMemo != NULL)) SavePacket(&pPack->header, fpMemo);
  328.  
  329.     /* If all of our bytes weren't sent, this will cause the 
  330.        scrolling graph to indicate as such.  */
  331.     if (nBytesSent < 0)
  332.     {
  333.         GraphInfo.BErrorS |= TRUE;
  334.         return(FALSE);
  335.     }         
  336.     return(TRUE);
  337. }
  338.  
  339.  
  340. ULONG PhoneWait(ULONG Mask)
  341. {
  342.     static struct fd_set fsReadSet, fsWriteSet;
  343.     int nMaxSocket = -1;
  344.     
  345.     if (sTCPSocket > nMaxSocket) nMaxSocket = sTCPSocket;
  346.     if (sUDPSocket > nMaxSocket) nMaxSocket = sUDPSocket;
  347.     
  348.     if (SocketBase)
  349.     {
  350.         FD_ZERO(&fsReadSet);              /* Initialize socket read set */
  351.         FD_ZERO(&fsWriteSet);
  352.         
  353.         if (sTCPSocket != -1) 
  354.         {
  355.             FD_SET(sTCPSocket, &fsReadSet);
  356.             if (TCPQueueLength(0) > 0) FD_SET(sTCPSocket, &fsWriteSet);
  357.         }
  358.     
  359.         WaitSelect(nMaxSocket+1, &fsReadSet, &fsWriteSet, NULL, NULL, &Mask);
  360.             
  361.         if (FD_ISSET(sTCPSocket, &fsReadSet)) ProcessReply();
  362.         if (FD_ISSET(sTCPSocket, &fsWriteSet)) 
  363.         {
  364.             ulBytesSentSince += ReduceTCPQueue(0,sTCPSocket);
  365.             SetWindowTitle(NULL);
  366.         }
  367.         
  368.         return(Mask);
  369.     }
  370.     else return(Wait(Mask));
  371. }